import csv, datetime, operator
class MFD:
    def __init__(self, src):
        """load the mean frequency distribution data into an object"""
        labels = '10day    5day    72hr    48hr    24hr    18hr    12hr    6hr    3hr    2hr    1hr    30min    15min    10min    5min'.split()
        days = [datetime.timedelta(days=x) for x in [10, 5, 3, 2, 1, 0.75,0.5,0.25,3.0/24,2.0/24,1.0/24,30.0/60/24,15.0/60/24, 10.0/60/24,5.0/60/24]]
        self.duration = zip(labels, days)
        self.frequencies = '2month    3month    4month    6month    9month    1year    2year    5year    10year    25year    50year    100year'.split()

        f = open(src)
        reader = csv.reader(f)
        h = reader.next()
        data = {}
        for l in reader:
            
            r = dict(zip(h, l))
            
            for k, v in r.items():
                if k in ('section', 'duration'):
                    pass
                else:
                    r[k] = float(v)
            
            section = data.setdefault(r['section'], {})
            section[r['duration']] = r
        f.close()

        self.table = data
    
    def rainfallStat(self, ts):
        """calculate the statistics of a rainfall timeseries
        ts: dict, {ts: [(time, rainfall), ,,,timestep: datetime.timedelta(minutes=5)]}"""
        
        def ts_summary(ts):
            
            time_list = [x[0] for x in ts['ts']]
            time_from = min(time_list)
            time_to = max(time_list) 
            value_list = [x[1] for x in ts['ts']]
            total_rainfall = sum(value_list)
            duration = time_to - time_from + ts['timestep']
            
            return {'from': time_from, 'to': time_to, 'total': total_rainfall, 'duration': duration}
        #a dict of frequencies {'10days': datetime.timedelta(days=10),,,}
        
        
        #the return results, init.
        results = {'summary': [], 'timestep': ts['timestep']}
        for k, v in ts_summary(ts).items():
            results[k] = v
        
        #get available frequency, show shorter than the duration of the storm and longer than the timestep
        #available_durations = [(k, v) for k, v in frequencies if v>=ts['timestep'] and v<=(results['to'] - results['from'])]
        
        #get the summary for each duration
        duration_list = [x[1] for x in self.duration] + [results['duration']]
        duration_list.sort()
        idx = duration_list.index(results['duration'])
        available_durations = duration_list[:idx+2]
        
            
        
        
        
        for k, v in self.duration:
            # for duration k, return interval v
            avg_list = [] #the list that will be used to calcuate the average for selected interval
            for t, r in ts['ts']:
                #query the rainfall readings within the return interval for current time step 
                selected = [x for x in ts['ts'] if x[0]>(t - v) and x[0]<=t]
                result = ts_summary({'ts': selected, 'timestep': ts['timestep']})
                avg_list.append(result)
            tmax = {'total': 0}
            #find the max value for that duration
            for x in avg_list:
                if x['total']>tmax['total']:
                    tmax = x.copy()
            if v in available_durations:
#            if ts['timestep']> v:
#                pass#results['summary'].append({'frequency': k, 'rainfall': -1, 'from': tmax['from'], 'to': tmax['to']})
#            else:
                results['summary'].append({'frequency': k, 'rainfall': tmax['total'], 'from': tmax['from'], 'to': tmax['to']})
        return results
            
            
                    
                    
                
            
                                     
                
        
        
        
    
    def getFrequency(self, duration, rainfall, section='05'):
        """Give the duration and rainfall, return the frequency
        duration: string , eg. 2month, 10year
        rainfall: float (in), eg. 1.5
        """
        distribution = self.table[section][duration]
        freq_list = [(k, distribution[k]) for k in self.frequencies]
        
        sorted_list = sorted(freq_list + [('storm', rainfall)], key=operator.itemgetter(1))
        idx = sorted_list.index(('storm', rainfall))
        if idx==0:
            return sorted_list[1][0]
        elif idx==len(sorted_list)-1:
            return sorted_list[idx-1][0]
        else:
            minInt = sorted_list[idx-1]
            maxInt = sorted_list[idx+1]
            if rainfall==maxInt[1]:
                return maxInt[0]
            else:
                return minInt[0]

        
        
    def getFD(self, storm):
        """give a storm and return a frequency"""
        duration = storm.get('duration')
        total = storm.get('total')
        
        if duration and total:
            
            sorted_list = sorted(self.duration + [('storm', duration)], key=operator.itemgetter(1))
            idx = sorted_list.index(('storm', duration))
            if idx==0:
                return sorted_list[1][0]
            elif idx==len(sorted_list)-1:
                return sorted_list[idx-1][0]
            else:
                minInt = sorted_list[idx-1]
                maxInt = sorted_list[idx+1]
                if duration==minInt[1]:
                    return minInt[0]
                else:
                    return maxInt[0]


#src = r'C:\dropbox\My Dropbox\projects\pystorm\data\Sectional_mean_frequency_distribution_for_storm.csv'
#mfd = MFD(src)
#
#for t in [10, 15,4,5, 3.2,3, 2.5,2,1.5, 1,0.8, 0.75,0.65,0.5,0.3,0.25,3.0/24,2.0/24,1.0/24,30.0/60/24,15.0/60/24, 10.0/60/24,5.0/10/24]:
#    duration = datetime.timedelta(days=t)
#    print '%s => %s' % (t, mfd.getFD({'duration': duration, 'total': 1.5}))
#
#for (duration, rainfall) in [('10day', 1.85), ('10day', 2.18), ('10day', 2.1), ('5min', 0.55), ('5min', 0.56)]:
#    print duration, rainfall, mfd.getFrequency(duration, rainfall)
#import pyodbc
#def get_cursor(db, password):
#    """
#    A helper function to return a cursor to the MDB file
#    """
#    conn_str = 'DRIVER={Microsoft Access Driver (*.mdb)};DBQ=%s;PWD=%s' % (db, password)
#    cnxn = pyodbc.connect(conn_str)
#    return cnxn.cursor()
#
#db = r'C:\dropbox\My Dropbox\projects\pystorm\data\rainfall.mdb'
#password = ''
#
#cursor = get_cursor(db, password)
#
#ts_list = []
#for r in cursor.execute('select top 100 * from rg24 order by [time];'):
#     ts_list.append((r.time, r.rainfall))
#
#ts = {'ts': ts_list, 'timestep': datetime.timedelta(minutes=5)}
#print '*'*50
#result =  mfd.rainfallStat(ts)
#for k, v in result.items():
#    print k, ':', v
#    if k=='summary':
#        for x in v:
#            print x['rainfall'], x['frequency'], mfd.getFrequency(x['frequency'],x['rainfall'] )
#            
